#include "rrshading.h"

#include <cmath>
#include <cstdio>

RRShading::RRShading()
{
    light[0] = -8.0f;
    light[1] = -6.0f;
    light[2] = 0.0f;

    for(int i=1; i<4; i++) {
        Kdiff[i] = 0.8f;
        Ldiff[i] = 1.0f;
        Kspec[i] = 0.8f;
        Lspec[i] = 1.0f;
        Kamb[i] = 0.1f;
        Lamb[i] = 0.5f;
    }
    Kdiff[0] = 1.0f;
    Ldiff[0] = 1.0f;
    Kspec[0] = 1.0f;
    Lspec[0] = 1.0f;
    Kamb[0] = 1.0f;
    Lamb[0] = 1.0f;

    Kshi = 20;
}

void RRShading::rrShading(RRPrim *arg)
{
    RRVertex *vp;
    float ToLight[3];
    float Reflect[3];
    float len1, len2;
    float InnerProduct;
    float Idiff[4], Ispec[4];
    int vnum;
    vnum = arg->rrGetVertsNum();
    for(int i=0; i<vnum; i++) {
        vp = arg->rrGetVertAdrs(i);
        ToLight[0] = light[0] - vp->x;
        ToLight[1] = light[1] - vp->y;
        ToLight[2] = light[2] - vp->z;
        len1 = sqrtf(ToLight[0] * ToLight[0] + ToLight[1] * ToLight[1] + ToLight[2] * ToLight[2]);
        InnerProduct = (ToLight[0] * vp->nx + ToLight[1] * vp->ny + ToLight[2] * vp->nz) / len1;
        if(InnerProduct < 0) { Idiff[1] = 0.0f; Idiff[2] = 0.0f; Idiff[3] = 0.0f; }
        else
            for(int i=1; i<4; i++)
                Idiff[i] = InnerProduct * Kdiff[i] * Ldiff[i];

        Reflect[0] = 2 * InnerProduct * vp->nx - ToLight[0] / len1;
        Reflect[1] = 2 * InnerProduct * vp->ny - ToLight[1] / len1;
        Reflect[2] = 2 * InnerProduct * vp->nz - ToLight[2] / len1;
        len1 = sqrtf(Reflect[0] * Reflect[0] + Reflect[1] * Reflect[1] + Reflect[2] * Reflect[2]);
        len2 = sqrtf(vp->x * vp->x + vp->y * vp->y + vp->z * vp->z);
        InnerProduct = (Reflect[0] * (vp->x) + Reflect[1] * (vp->y) + Reflect[2] *(-vp->z)) / (len1 * len2);
        if(InnerProduct < 0) { Ispec[1] = 0.0f; Ispec[2] = 0.0f; Ispec[3] = 0.0f; }
        else
            for(int i=1; i<4; i++)
                Ispec[i] = powf(InnerProduct, Kshi) * Kspec[i] * Lspec[i];

        for(int i=1; i<4; i++) {
            vp->c[i] = vp->c[i] * Idiff[i] + Ispec[i] + Kamb[i] * Lamb[i];
            if(vp->c[i] > 1.0f) vp->c[i] = 1.0f;
            //printf("%f %f %f\n", Ispec[1], Ispec[2], Ispec[3]);
        }
    }
}
